var heldCallId=null;
function CTI(serverUrl) {
    // *********************************************************************
	// Private methods & variables
	
	argumentNotNull(serverUrl, "serverUrl");
		
	const _instance = this;
	const _serverUrl = serverUrl;
	const _eventHubUrl = serverUrl + "agentEvent";
	
	const isIE = browserIsIE();	
	const JSONParser = (typeof JSON === "object" && typeof JSON.parse === "function") ? JSON.parse : function(data){ return eval("(" + data + ")")};
		
	var _agentId = null;
	var _sessionId = null;	
	var _heartBeatTimer = null;
	var _eventHub = null;	
	var _eventPoller = null;
	var hour,minute,second;//时 分 秒
	hour=minute=second=0;//初始化

	var int;
	var millisecond=0;//毫秒
	function Reset()//重置
	{
		window.clearInterval(int);
		millisecond=hour=minute=second=0;
		document.getElementById('ztai').innerHTML='00时00分00秒';
	}

	function start()//开始
	{
		cti_baochi();
		int=setInterval(timer,1000);
	}
	//计时
	function timer(){
		second++;
		if(second>=60){
			second=0;
			minute=minute+1;
		}

		if(minute>=60){
			minute=0;
			hour=hour+1;
		}
		document.getElementById('ztai').innerHTML='通话中:'+hour+'时'+minute+'分'+second+'秒';

	}

	// 检查参数是否为空
    function argumentNotNull(value, name) {
        if (value == undefined || value == null) {
            throw new Error("Argument '" + name + "' cannot be null.");
        }
    }
	
	// 检查浏览器是否 IE
    function browserIsIE() {

        //取得浏览器的userAgent字符串
        var userAgent = navigator.userAgent;

        if (userAgent != undefined && userAgent != null) {
            return userAgent.indexOf("MSIE") > -1;
        }

        return false;
    }
	
	// 检查是否已登录，如果未登录则抛出异常
	function ensureLoggedIn() {		
		if(_sessionId == undefined || _sessionId == null) {
			throw new Error("Agent not logged in.");
		}
	}
	
	//
	function invoke(target, argsArray) {		
		if(typeof target === "function") {			
			target.apply(null, argsArray);
		}
	}
	
    // Create XHR
    function createRequest() {
		
        var xhr = null;
		
        if (window.XMLHttpRequest) {
            xhr = new XMLHttpRequest();
        }
        else {
            xhr = new ActiveXObject("Microsoft.XMLHTTP");
        }
		
        return xhr;
    }
	
	//
	function parseJSON(data) {
		
		if(!data) {
			throw new Error("Failed to parse json data.");
		}
		
		return JSONParser(data);
	}
	
	function httpAPIGet(action, options) {
		httpAPICall("GET", action, null, null, options);
	}
	
	function httpAPIPost(action, data, contentType, options) {
		httpAPICall("POST", action, data, contentType, options);
	}
	
	// 
	function httpAPICall(method, action, data, contentType, options) {
		
		options = options || {};
		
		var xhr = createRequest();
        xhr.open(method, _serverUrl + action);
        xhr.setRequestHeader("If-Modified-Since", "0");
        xhr.setRequestHeader('X-Request-With', null);
		
		if(contentType){
			xhr.setRequestHeader("Content-Type", contentType);
		}
		else{
			xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
		}
		
		if(_sessionId != null){
			xhr.setRequestHeader("JSESSIONID", _sessionId);
		}
		
		xhr.onreadystatechange = function() {
			
			if(xhr.readyState == 4) {
				
				if(xhr.status == 0) {
					invoke(options.error, [{result: -1, message: "API request failed."}]);
				}
				else if(xhr.status != 200) {
					invoke(options.error, [{result: -2, message: "API request failed with status code " + xhr.status + ", " + xhr.statusText}]);
				}
				else {
					var json = null;
					
					try {
						json = parseJSON(xhr.responseText);						
					}
					catch(e) {					
						invoke(options.error, [{result: -3, message: e.message}]);						
						return;
					}
					
					try {
						
						if(json.code === 0) {						
							invoke(options.success, [json]);
						}
						else {
							invoke(options.error, [json]);
						}
					}
					catch (e) {
						
					}
				}
			}
		}
		
		if (data == undefined || data == null) {
            xhr.send();
        }
        else {
            xhr.send(data);
        }
	}
	
	//
	function httpAPICallSync(method, action, data, contentType) {
		
		var xhr = createRequest();
        xhr.open(method, _serverUrl + action, false);
        xhr.setRequestHeader("If-Modified-Since", "0");
        xhr.setRequestHeader('X-Request-With', null);
		
		if(contentType){
			xhr.setRequestHeader("Content-Type", contentType);
		}
		else{
			xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
		}
		
		if(_sessionId != null){
			xhr.setRequestHeader("JSESSIONID", _sessionId);
		}
		
		if (data == undefined || data == null) {
            xhr.send();
        }
        else {
            xhr.send(data);
        }
		
		if(xhr.status == 0) {		
			throw new Error("API request failed.");			
		}
		else if(xhr.status != 200) {
			throw new Error("API request failed with status code " + xhr.status + ", " + xhr.statusText);
		}
		
		var json = null;
		
		try {
			json = parseJSON(xhr.responseText);						
		}
		catch(e) {					
			throw new Error("API request failed caused by invalid response data.");
		}
		
		return json;
	}
	
	//
	function startHeartbeatTimer() {
		
		if(_heartBeatTimer) {
			window.clearInterval(_heartBeatTimer);			
		}
		
		_heartBeatTimer = window.setInterval(function() {
			
			if(_sessionId == null) {
				return;
			}
			
			httpAPIGet("heartbeat");
			
		}, 30000);
	}
	
	//
	function onLoggedOut() {
		
		var ssid = _sessionId;
		
		_agentId = null;
		_sessionId = null;
		
		/*
		if(_eventHub) {
			_eventHub.stop();
			_eventHub = null;
		}
		*/
		
		detachEvent();
		
		if(_heartBeatTimer)	{
			window.clearInterval(_heartBeatTimer);
			_heartBeatTimer = null;
		}
		
		if(ssid) {
			invoke(_instance.onAgentLoggedOut, []);
		}
	}
	
	//
	function EventPoller(agentId, sessionId) {
		
		let aid = agentId;
		let sid = sessionId;
		let running = false;			
		let eventxhr = null;
		
		this.isRunning = function() {
			return running
		};
		
		this.start = function() {
			
			if (!running) {
				
				running = true;				
				getEvent();
				
				console.log("EventPoller started");
			}
		};
		
		this.stop = function() {
			
			if(running) {
				
				running = false;
				
				if(eventxhr) {
					eventxhr.abort();
				}
				
				httpAPIGet("stoppollevent?agentId=" + encodeURIComponent(aid) + "&sessionId=" + encodeURIComponent(sid)); 
				
				console.log("EventPoller stopped");
			}
		}
		
		function getEvent() {

			try {

				if (!running) {
					return;
				}

				eventxhr = createRequest();
				eventxhr.open("GET", _serverUrl + "pollevent?agentId=" + encodeURIComponent(aid) + "&sessionId=" + encodeURIComponent(sid), true);
				eventxhr.setRequestHeader("If-Modified-Since", "0");

				if (isIE) {

					eventxhr.onreadystatechange = function () {

						if (eventxhr.readyState == 4) {
							
							if (eventxhr.status == 200) {                            
								processEventResult(eventxhr.responseText);							
							}
							
							if (running) {
								getEvent();
							}
						}
					}
				}
				else {

					eventxhr.onloadend = function () {

						if (eventxhr.status == 200) {
							processEventResult(eventxhr.responseText);
						}
						
						if (running) {
							getEvent();
						}
					}
				}

				eventxhr.send();
			}
			catch (e) {
				console.error("poll event failed. " + e);
			}
		}
	}
	
	//
	function attachEvent() {
		
		if(!_agentId || !_sessionId){
			console.error("attach event failed, invalid sessionId.");
			return;
		}
		
		if(!_eventPoller || !_eventPoller.isRunning()) {			
			_eventPoller = new EventPoller(_agentId, _sessionId);
			_eventPoller.start();
		}
	}
	
	//
	function detachEvent() {
		
		if(_eventPoller) {
			_eventPoller.stop();
		}
	}
		
	/*
	function attachEvent() {
		
		if(!_agentId){
			console.error("attach event failed, invalid agentId.");
			//return;
		}
		
		let url = _eventHubUrl + (_eventHubUrl.indexOf('?') == -1 ? "?": "&") + "agentId=" + encodeURIComponent(_agentId);
				
		_eventHub = new signalR.HubConnectionBuilder()
			.withUrl(url)
			.withAutomaticReconnect()
			.build();

		_eventHub.on("agentEvent", data => {
			processEvent(data);
		});

		try {
			_eventHub.start();
			console.log("attach event successfully.");
		}
		catch (err) {
			console.error("attach event failed, " + err);
		}
	}
	*/
	
	// 处理时间
	function processEventResult(res) {
		
		if(res == undefined || res == null) {
			return;
		}
		
		var json = JSONParser(res);
		
		if(json.code === 0) {
			processEvent(json.data);
		}	
	}
	
	// 处理事件
	function processEvent(data) {
		
		if(data == undefined || data == null) {
			return;
		}
		
		try	{
			
			var evt = JSONParser(data);	
			
			switch (evt.event) {

                case "AGENT_STATE_CHANGE":
					
					invoke(_instance.onAgentStateChanged, [evt]);
					
					if(evt.newState == 0) {	
						onLoggedOut();
					}
					
                    break;
				
				case "AGENT_CALL_RINGING":
					
					invoke(_instance.onCallRinging, [evt]);					
					break;
					
				case "AGENT_CALL_DIALING":
					
					invoke(_instance.onCallDialing, [evt]);					
					break;
					
				case "AGENT_CALL_OUT_FAIL":
					
					invoke(_instance.onCallOutFailed, [evt]);					
					break;
					
				case "AGENT_CALL_INNER_FAIL":
					
					invoke(_instance.onCallInnerFailed, [evt]);
					break;
					
				case "AGENT_CALL_CONSULT_OUT_SUCC":
					
					invoke(_instance.onConsultOutSucc, [evt]);
					break;
					
				case "AGENT_CALL_CONSULT_OUT_FAIL":
					
					invoke(_instance.onConsultOutFailed, [evt]);
					break;
					
				case "AGENT_CALL_CONSULT_AGENT_SUCC":
					
					invoke(_instance.onConsultAgentSucc, [evt]);					
					break;
					
				case "AGENT_CALL_CONSULT_AGENT_FAIL":
					
					invoke(_instance.onConsultAgentFailed, [evt]);					
					break;
					
				case "AGENT_CALL_RECORD":
					
					invoke(_instance.onCallRecord, [evt]);					
					break;
					
				case "AGENT_CALL_TALKING":
					
					invoke(_instance.onCallTalking, [evt]);					
					break;
					
				case "AGENT_CALL_ONHOLD":
					
					invoke(_instance.onCallHold, [evt]);					
					break;
					
				case "AGENT_CALL_UNHOLD":
					
					invoke(_instance.onCallUnhold, [evt]);
					break;

				case "AGENT_CALL_RELEASE":
					
					invoke(_instance.onCallReleased, [evt]);
					break;
					
				case "AGENT_CALL_REPLACED":
					
					invoke(_instance.onCallReplaced, [evt]);
					break;
					
                default:
					
					console.log("Unhandled CTI event: %o", evt);
                    break;
            }
		}
		catch(e) {
			console.log("process event failed. " + e.message);
		}
	}
	
    // *********************************************************************
    // 事件回调
	
	// 坐席登录
	this.onAgentLoggedIn = function(e) {
		console.log("Agent logged in.");
	}

	// 坐席注销登录
	this.onAgentLoggedOut = function(e) {
		console.log("Agent logged out.");
	}
	
    // 坐席状态改变事件
    this.onAgentStateChanged = function (e) { 
		console.log("Agent state changed, newState: " + e.newState);
	}
	
	// 呼入
	this.onCallRinging = function(e) {
		cti_jieting();
		console.log("Call ringing, callId: " + e.callId + ", caller: " + e.caller + ", callee: " + e.callee);
	}
	
	// 呼出
	this.onCallDialing = function(e) {
		console.log("Call dialing, callId: " + e.callId + ", caller: " + e.caller + ", callee: " + e.callee);
	}
	
	// 外呼失败
	this.onCallOutFailed = function(e) {
		console.log("Call out failed, callId: " + e.callId + ", reason: " + e.reason);
	}

	// 协商外线成功
	this.onConsultOutSucc = function(e) {
		console.log("Consult out success, callId: " + e.callId);
	}
	
	// 协商外线失败
	this.onConsultOutFailed = function(e) {
		console.log("Consult out failed, callId: " + e.callId + ", reason: " + e.reason);
	}
	
	// 呼叫坐席失败
	this.onCallInnerFailed = function(e) {
		console.log("Call inner failed, callId: " + e.callId + ", reason: " + e.reason);
	}
	
	// 协商坐席成功
	this.onConsultAgentSucc = function(e) {
		console.log("Consult agent success, callId: " + e.callId);
	}
	
	// 协商坐席失败
	this.onConsultAgentFailed = function(e) {
		console.log("Consult agent failed, callId: " + e.callId + ", reason: " + e.reason);
	}
	
	// 录音
	this.onCallRecord = function(e) {
		console.log("Call record, callId: " + e.callId + ", fileName: " + e.fileName);
	}
	
	// 通话
	this.onCallTalking = function(e) {
		start();
		console.log("Call talking, callId: " + e.callId + ", caller: " + e.caller + ", callee: " + e.callee);
	}
	
	// 保持
	this.onCallHold = function(e) {
		heldCallId = null;
		// 保存标识
		heldCallId = e.callId;
		console.log("Call hold, callId: " + e.callId);
	}
    
	// 取消保持
	this.onCallUnhold = function(e) {
		console.log("Call resume, callId: " + e.callId);
	}
	
	// 呼叫替换（被协商连接保持）
	this.onCallReplaced = function(e) {
		console.log("Call replaced, callId: " + e.callId);
	}
	
	// 挂断
	this.onCallReleased = function(e) {
		cti_qianru();
		Reset();
		document.getElementById('ztai').innerHTML='话后';
		console.log("Call released, callId: " + e.callId);
	}
	
    // *********************************************************************
	
	// 是否已登录
	this.isLoggedIn = function() {
		return _sessionId != undefined && _sessionId != null;
	}
	
	// 获取当前登录会话标识
	this.getSessionId = function() {
		return _sessionId;
	}
	
	// 挂载登录会话
	// 参数：
	//		sessionId	会话标识
	//		options		回调对象
	this.attachSession = function(sessionId, options) {
		
		argumentNotNull(sessionId, "sessionId");
		
		if(this.isLoggedIn()) {			
			throw new Error("Agent already logged in.");
		}
		
		options = options || {};

		httpAPIGet("getSession?sessionId=" + encodeURIComponent(sessionId), 
		{
			success: function(result) {
				
				_agentId = result.data.agentId;
				_sessionId = result.data.sessionId;
				
				attachEvent();
				
				startHeartbeatTimer();
				
				invoke(options.success, [result]);				
				invoke(_instance.onAgentLoggedIn, [result.data]);
			},
			
			error: function(e) {				
				invoke(options.error, [e]);
			}
		});		
	}
	
    // 登录
    // 参数：
    //      agentId      	工号
    //      agentSecret    	密码
    //      phone    		电话号码
    //      initialReady    是否自动示闲
	// 		forceLogin		是否强制登录
	//		options			回调对象
    this.login = function (agentId, agentSecret, phone, initialReady, forceLogin, options) {
		
        argumentNotNull(agentId, "agentId");
        argumentNotNull(phone, "phone");
						
		options = options || {};
		
		if(this.isLoggedIn()) {			
			throw new Error("Agent already logged in.");
		}
		
		agentSecret = agentSecret || "";
		initialReady = initialReady || false;
		forceLogin = forceLogin || false;
		
		var auth = agentId + ";" + agentSecret;
		auth = md5(auth);
		
		var loginData = "agentId=" + encodeURIComponent(agentId) 
					+ "&phone=" + encodeURIComponent(phone) 
					+ "&authorization=" + encodeURIComponent(auth)
					+ "&initialReady=" + encodeURIComponent(initialReady) 
					+ "&forceLogin=" + encodeURIComponent(forceLogin);

		
		httpAPIGet("login?" + loginData, 
		{
			success: function(result) {
				
				_agentId = agentId;
				_sessionId = result.data.sessionId;
				
				attachEvent();
				
				startHeartbeatTimer();
				
				invoke(options.success, [result]);				
				invoke(_instance.onAgentLoggedIn, [result.data]);
			},
			
			error: function(e) {
				invoke(options.error, [e]);
			}
		});
	}
	
    // 注销登录
    // 参数：
	//			options			回调对象
    this.logout = function (options) {
        
		if(!this.isLoggedIn()) {
			return;
		}
		
		options = options || {};
		
		httpAPIGet("logout", 
		{
			success: function(result) {
				
				onLoggedOut();
				
				invoke(options.success, [result]);
			},
			error: function(e) {				
				invoke(options.error, [e]);
			}
		});
    }
	
	// 获取坐席状态
    // 参数：
	//			options			回调对象
	this.getAgentState = function(options) {
		
		options = options || {};
		
		if(!this.isLoggedIn()) {
			
			invoke(options.success, [{result: 0, data: {state: 0}}]);			
			return;
		}
		
		httpAPIGet("getAgentState", options);
	}
	
	// 获取坐席活动呼叫
    // 参数：
	//			options			回调对象
	this.getActiveCall = function(options) {
		
		ensureLoggedIn();
		
		httpAPIGet("getActiveCall", options);
	}
	
	// 示闲
    // 参数：
	//			options			回调对象
    this.setReady = function (options) {		
		
		ensureLoggedIn();
        
		httpAPIGet("setReady", options);		
    }
	
	// 示忙
    // 参数：
	//			options			回调对象
    this.setNotReady = function (options) {
		
		ensureLoggedIn();
        
		httpAPIGet("setNotReady", options);
    }

	// 查询坐席正在处理的呼叫列表
    // 参数：
	//			options			回调对象
    this.listCalls = function (options) {
		
		ensureLoggedIn();
		
        httpAPIGet("listCalls", options);
    }	
	
    // 呼叫应答
    // 参数：
	//			options			回调对象	
    this.answerCall = function (options) {
		
		ensureLoggedIn();
		
		httpAPIGet("answer", options);
    }
	
    // 外呼
    // 参数：
    //      	callerNumber  	主叫号码
    //      	calleeNumber  	被叫叫号码
	//			options			回调对象	
    this.callOut = function (callerNumber, calleeNumber, options) {
		
		argumentNotNull(calleeNumber, "calleeNumber");
		
		ensureLoggedIn();
		
		callerNumber = callerNumber || "";
		
        httpAPIGet("callOut?callerNumber=" + encodeURIComponent(callerNumber) + "&calleeNumber=" + encodeURIComponent(calleeNumber), options);
    }

	// 呼叫坐席
    // 参数：
    //      	calleeAgent  	被叫坐席
	//			options			回调对象
    this.callAgent = function (calleeAgent, options) {
		
		argumentNotNull(calleeAgent, "calleeAgent");
		
		ensureLoggedIn();
		
        httpAPIGet("callAgent?calleeAgent=" + encodeURIComponent(calleeAgent), options);
    }
	
    // 获取随路数据
    // 参数：
	//			options			回调对象
    this.getCallData = function (options) {
		
		ensureLoggedIn();
		
        httpAPIGet("getCallData", options);
    }

    // 设置随路数据
    // 参数：
    //      	callData   		随路数据
	//			options			回调对象
    this.setCallData = function (callData, options) {
		
		argumentNotNull(callData, "callData");
		
		ensureLoggedIn();
		
        httpAPIGet("setCallData", "callData=" + encodeURIComponent(callData), options);
    }
	
	// 保持呼叫
    // 参数：
	//			options			回调对象
    this.holdCall = function (options) {
		
		ensureLoggedIn();
		
        httpAPIGet("holdCall", options);
    }
	
	// 取保持
    // 参数：
    //      	callId   		呼叫标识
	//			options			回调对象
    this.retrieveHold = function (callId, options) {
		
		argumentNotNull(callId, "callId");
		
		ensureLoggedIn();
		
        httpAPIGet("retrieveCall?callId=" + encodeURIComponent(callId), options);
    }

	// 设置静音
    // 参数：
	//			options			回调对象
    this.setMuteOn = function (options) {
		
		ensureLoggedIn();
		
        httpAPIGet("setMuteOn", options);
    }
	
	// 取消静音
    // 参数：
	//			options			回调对象
    this.setMuteOff = function (options) {
		
		ensureLoggedIn();
		
        httpAPIGet("setMuteOff", options);
    }
	
	// 二次拨号
    // 参数：
    //      	digits			号码
	//			options			回调对象
    this.sendDTMF = function (digits, options) {
		
		ensureLoggedIn();
		
        httpAPIGet("sendDTMF?digits=" + encodeURIComponent(digits), options);
    }

    // 转外线
    // 参数：
    //      	calleeNumber   	目标号码
	//			options			回调对象
    this.transOut = function (calleeNumber, options) {
		
		argumentNotNull(calleeNumber, "calleeNumber");
		
		ensureLoggedIn();
		
        httpAPIGet("transOut?calleeNumber=" + encodeURIComponent(calleeNumber), options);
    }
	
    // 转坐席
    // 参数：
    //      	calleeAgent   	目标号码
	//			options			回调对象
    this.transAgent = function (calleeAgent, options) {
		
		argumentNotNull(calleeAgent, "calleeAgent");
		
		ensureLoggedIn();
		
        httpAPIGet("transAgent?calleeAgent=" + encodeURIComponent(calleeAgent), options);
    }
	
    // 转队列
    // 参数：
    //      	queueId   		队列ID
	//			options			回调对象
    this.transQueue = function (queueId, options) {
		
		argumentNotNull(queueId, "queueId");
		
		ensureLoggedIn();
		
        httpAPIGet("transQueue?queueId=" + encodeURIComponent(queueId), options);
    }
	
    // 转 IVR
    // 参数：
    //      	ivrId   		IVR ID
	//			options			回调对象
    this.transIVR = function (ivrId, options) {
		
		argumentNotNull(ivrId, "ivrId");
		
		ensureLoggedIn();
		
        httpAPIGet("transIVR?ivrId=" + encodeURIComponent(ivrId), options);
    }
	
	// 协商坐席或外线
    // 参数：
    //      	calleeNumber	目标号码或坐席工号
	//			options			回调对象
    this.consult = function (calleeNumber, options) {
		
		argumentNotNull(calleeNumber, "calleeNumber");
		
		ensureLoggedIn();
		
		var json = httpAPICallSync("GET", "queryAgent?agentId=" + encodeURIComponent(calleeNumber));
		
		if(json.code == 0) {
			httpAPIGet("consultAgent?calleeAgent=" + encodeURIComponent(calleeNumber), options);
		}
		else {
			httpAPIGet("consultOut?calleeNumber=" + encodeURIComponent(calleeNumber), options);
		}
    }
	
    // 协商坐席
    // 参数：
    //      	calleeAgent 	目标坐席
	//			options			回调对象
    this.consultAgent = function (calleeAgent, options) {
		
		argumentNotNull(calleeAgent, "calleeAgent");
		
		ensureLoggedIn();
		
        httpAPIGet("consultAgent?calleeAgent=" + encodeURIComponent(calleeAgent), options);
    }
	
    // 协商外线
    // 参数：
    //      	calleeNumber	目标号码
	//			options			回调对象
    this.consultOut = function (calleeNumber, options) {
		
		argumentNotNull(calleeNumber, "calleeNumber");
		
		ensureLoggedIn();
		
        httpAPIGet("consultOut?calleeNumber=" + encodeURIComponent(calleeNumber), options);
    }
	
    // 连接保持（协商成功后转接）
    // 参数：
    //      	heldCallId	保持的呼叫标识
	//			options	 	回调对象
    this.connectHold = function (heldCallId, options) {
		
		argumentNotNull(heldCallId, "heldCallId");
		
		ensureLoggedIn();
		
        httpAPIGet("connectHold?heldCallId=" + encodeURIComponent(heldCallId), options);
    }
	
    // 三方通话
    // 参数：
	//			options	 	回调对象
    this.conference = function (options) {
		
		ensureLoggedIn();
		
        httpAPIGet("conference", options);
    }
	
    // 释放呼叫（挂机）
    // 参数：
	//			options	 	回调对象
    this.releaseCall = function (options) {
		
		ensureLoggedIn();
		
        httpAPIGet("releaseCall", options);
    }
	
	// 查询全部坐席
    // 参数：
	//			options	 	回调对象
    this.listAgent = function (options) {
		
		ensureLoggedIn();
		
        httpAPIGet("listAgent", options);
    }
	
	// 查询在线坐席
    // 参数：
	//			options	 	回调对象
    this.listOnlineAgent = function (options) {
		
		ensureLoggedIn();
		
        httpAPIGet("listAgent?online=true", options);
    }
	
	// 查询签入指定队列的坐席
    // 参数：
	//			queueId		队列ID
	//			options	 	回调对象
    this.listAgentByQueue = function (queueId, options) {
		
		argumentNotNull(queueId, "queueId");
		
		ensureLoggedIn();
		
        httpAPIGet("listAgentByQueue?queueId=" + encodeURIComponent(queueId), options);
    }
	
	// 查询队列
    // 参数：
	//			options	 	回调对象
    this.listQueue = function (options) {
		
		ensureLoggedIn();
		
        httpAPIGet("listQueue", options);
    }
	
	// 查询IVR
    // 参数：
	//			options	 	回调对象
    this.listIVR = function (options) {
		
		ensureLoggedIn();
		
        httpAPIGet("listIVR", options);
    }
	
	// 强制示闲
	// 参数：
	//			agentId  	要操作的坐席工号
	//			options	 	回调对象
	this.forceAgentReady = function (agentId, options) {
		
		ensureLoggedIn();
		
		httpAPIGet("forceReady?agentId=" + encodeURIComponent(agentId), options);
	}
	
	// 强制示忙
	// 参数：
	//			agentId  	要操作的坐席工号
	//			options	 	回调对象
	this.forceAgentBusy = function (agentId, options) {
		
		ensureLoggedIn();
		
		httpAPIGet("forceBusy?agentId=" + encodeURIComponent(agentId), options);
	}
	
	// 强制签出
	// 参数：
	//			agentId  	要操作的坐席工号
	//			options	 	回调对象
	this.forceAgentOut = function (agentId, options) {
		
		ensureLoggedIn();
		
		httpAPIGet("forceOut?agentId=" + encodeURIComponent(agentId), options);
	}
	
	// 获取坐席监控数据
    // 参数：
	//			options	 	回调对象
    this.getAgentMonitorData = function (online, options) {
		
		ensureLoggedIn();
		
        httpAPIGet("AgentMonitorData?online=" + online, options);
    }
	
		// 获取坐席监控数据
    // 参数：
	//			options	 	回调对象
    this.getQueueMonitorData = function (options) {
		
		ensureLoggedIn();
		
        httpAPIGet("QueueMonitorData", options);
    }
	
    // *********************************************************************
}